package com.wjv.example.spbt.task.service;

import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;

/**
 * <p>Title: MyThreadPool</p>
 *
 * @author zmj
 * @since 2022/2/7 13:29
 */
public class MyThreadPool {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyThreadPool.class);

    private static final int CORE_POOL_SIZE = Runtime.getRuntime().availableProcessors() * 4;

    private static final int MAXIMUM_POOL_SIZE = CORE_POOL_SIZE + 10;

    private static final String THREAD_POOL_NAME = "my-thread-pool-%d";

    private static final ThreadFactory FACTORY =
            new BasicThreadFactory.Builder().namingPattern(THREAD_POOL_NAME).build();

    private static final int DEFAULT_SIZE = 100000;

    private static final long DEFAULT_KEEP_ALIVE = 60L;

    private static ThreadPoolExecutor executor;

    private static BlockingQueue<Runnable> executeQueue =
            new ArrayBlockingQueue<Runnable>(DEFAULT_SIZE);

    static {
        LOGGER.info("初始化线程池: {}", THREAD_POOL_NAME);
        try {
            executor = new ThreadPoolExecutor(CORE_POOL_SIZE,
                    MAXIMUM_POOL_SIZE,
                    DEFAULT_KEEP_ALIVE,
                    TimeUnit.SECONDS,
                    executeQueue,
                    FACTORY,
                    new ThreadPoolExecutor.CallerRunsPolicy()) {

                @Override
                protected void afterExecute(Runnable r, Throwable t) {
                    // 初始线程数、核心线程数、正在执行的任务数量、
                    // 已完成任务数量、任务总数、队列里缓存的任务数量、池中存在的最大线程数、
                    // 最大允许的线程数、线程空闲时间、线程池是否关闭、线程池是否终止
                    LOGGER.info("PoolSize: {}, " +
                                    "CorePoolSize: {}, " +
                                    "Active: {}, " +
                                    "Completed: {}, " +
                                    "Task: {}, " +
                                    "Queue: {}, " +
                                    "LargestPoolSize: {}, " +
                                    "MaximumPoolSize: {}, " +
                                    "KeepAliveTime: {}s, " +
                                    "isShutdown: {}, " +
                                    "isTerminated: {}",
                            this.getPoolSize(),
                            this.getCorePoolSize(),
                            this.getActiveCount(),
                            this.getCompletedTaskCount(),
                            this.getTaskCount(),
                            this.getQueue().size(),
                            this.getLargestPoolSize(),
                            this.getMaximumPoolSize(),
                            this.getKeepAliveTime(TimeUnit.SECONDS),
                            this.isShutdown(),
                            this.isTerminated());
                }
            };
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    private MyThreadPool() {

    }

    public static boolean execute(Runnable task) {
        try {
            executor.execute(task);
        } catch (RejectedExecutionException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public static <T> Future<T> submitTask(Callable<T> task) {
        try {
            return executor.submit(task);
        } catch (Exception e) {
            e.printStackTrace();
            throw new UnsupportedOperationException("Unable to submit the task, rejected.", e);
        }
    }
}
